package client;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.ZipLocator;
import com.jme3.collision.CollisionResults;
import com.jme3.font.BitmapText;
import com.jme3.light.PointLight;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.post.FilterPostProcessor;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.system.AppSettings;
import java.util.ArrayList;
import java.util.logging.Level;

/**
 * @Author Ben
 * @Original hello_terrain example by Brent Owens
 * All remnants of original code are used within reason and fair use of the JME3 license.
 */
public class Main extends SimpleApplication 
{
    /*
    variable types
    BitmapText: text read from a bitmap file
    PointLight: light cast from a point
    Geometry: vertices cast to a mesh
    Spatial: object defined in space
    */
    protected BitmapText hintText;
    static FilterPostProcessor fpp;
    static GameInterface gameinterface = new GameInterface();
    static SpawnController spawning = new SpawnController();
    static ObjectPlayer player = new ObjectPlayer();
    static ObjectNPC npchandle = new ObjectNPC();
    static LightingController lights = new LightingController();
    static TerrainControl terraincontrol = new TerrainControl();
    static InventoryController inventory = new InventoryController();
    static AnimationHelper animhelper = new AnimationHelper();
    static Main appref;
    static ConCmd console = new ConCmd();
    static NetworkController network = new NetworkController();
    static Spatial gameScene;
    static Node rendernode;
    static FileHandler filehandle = new FileHandler();
    static ArrayList<FloatingText> titles = new ArrayList();
    static AppSettings gameSetttings = new AppSettings(true);
    PointLight pl;
    Geometry lightMdl;
    Geometry selectedCollisionObject;
    
    /*
    Main:
    set the variable api as the started app for purposes of accesibility to other places in the program.
    */
    public static void main(String[] args) 
    {
        Main app = new Main();
        gameSetttings.setTitle("Lund - The Indecent RPG Experience");
        gameSetttings.setSettingsDialogImage("Textures/lundlogo.png");
        gameSetttings.setResolution(800, 600);
        app.setShowSettings(true);
        gameSetttings.setRenderer(AppSettings.LWJGL_OPENGL_ANY);
        app.setSettings(gameSetttings);
        app.start();
        appref = app;
    }

    @Override
    public void initialize() 
    {
        super.initialize();
    }
    
    public Vector2f getScr()
    {
        return new Vector2f(gameSetttings.getWidth(), gameSetttings.getHeight());
    }
    
    public static GameInterface getGI()
    {
        return gameinterface;
    }
    
    public float getFPS()
    {
        return timer.getFrameRate();
    }
    
    /*
    simpleInitApp:
    initialises the loading screen and starts the load process, further defined in gameinterface.java
    */
    @Override
    public void simpleInitApp() 
    {
        gameinterface.initLoadScreen();
        gameinterface.loadMenu();
    }

    @Override
    public void update() 
    {
        super.update();
    }   
    
    /*
    simpleUpdate:
    at first chects for a loading variable and if true, proceeds with the loading process, else goes into a regular game loop,
    each function is described more in its java file
    */    
    @Override
    public void simpleUpdate(float tpf) 
    {
        if(gameinterface.gameLoading)
        {
            if(gameinterface.frameCount == 1)
            {
                //low level: items, commands, data
                appref.setDisplayFps(true);
                rendernode = new Node();
                rendernode.setName("rendernode");
                rendernode.setCullHint(Spatial.CullHint.Never);
                gameinterface.loadConsole();
                java.util.logging.Logger.getLogger("").setLevel(Level.WARNING);
                console.load_commands(gameinterface.niftyConsoleC,gameinterface.nifty);
                DefinitionsItems.init_items();
                inventory.setupInventory();
                assetManager.registerLocator("maps.zip", ZipLocator.class.getName());
                NetworkController.registerMessages();
                Main.fpp = new FilterPostProcessor(Main.appref.getAssetManager());
                gameinterface.setLoadProgress(0.3f, "Recombobulating Discombobulators");
            }
            if(gameinterface.frameCount == 2)
            {
                //medium level: terrain and static world objects + physics engine
                PhysicsController.initPhysics(appref);
                terraincontrol.loadTerrain();
                terraincontrol.startWater();
                gameinterface.setLoadProgress(0.5f, "Recalculating the Incalculable");
            }
            if(gameinterface.frameCount == 3)
            {
                //high level: dynamic objects, player, lights etc.
                cam.setFrustum(1f, 2500.0f, -0.55f, 0.55f, 0.4125f, -0.4125f);
                cam.setLocation(new Vector3f(0, 25, -10));
                cam.lookAtDirection(new Vector3f(0, -1, 0).normalizeLocal(), Vector3f.UNIT_Y);
                player.setupKeys(this);
                player.initPlayer(this);
                player.initCrossHairs(this);
                player.playerTeleport(new Vector3f(0, 50, 50));
                player.createWire();
                lights.setupLight();
                lights.setupShadows();
                Main.appref.getViewPort().addProcessor(Main.fpp);
                gameinterface.setLoadProgress(0.7f, "Instantiating the null");
            }
            if(gameinterface.frameCount == 4)
            {
                //top level: interface and final things
                gameinterface.setLoadProgress(0.9f, "Indirectly directing the directions");
            }
            if(gameinterface.frameCount == 5)
            {
                Main.appref.getRootNode().attachChild(rendernode);
                gameinterface.finishLoad();
                gameinterface.startInterface(this);
            }
            gameinterface.frameCount++;
        }
        else
        {
                ViewPortState vp = Main.appref.getStateManager().getState(ViewPortState.class);
                player.playerUpdate(tpf, appref);
                if (gameinterface.barChange())
                {
                    if (player.isBuild)
                    {
                        player.reshapeWire(gameinterface.curbar);
                        player.resizeWire(player.choiceSize, gameinterface.curbar);
                    }
                    gameinterface.curbarLastPoll = gameinterface.curbar;
                }
                player.moveWire(player.getLook().add(new Vector3f(0, player.choiceSize, 0)));
                player.timeSync();
                gameinterface.updateNumbers();
                npchandle.timeSync();
                vp.alignLights();
        }
    }
    
    
    /*
    testCollision:
    moves the collison testing sphere to the collide location, soon to be deprecated
    */
    private void testCollision(Vector3f oldLoc) 
    {
        if (TerrainControl.getTerrain().collideWith(selectedCollisionObject.getWorldBound(), new CollisionResults()) > 0) 
        {
            selectedCollisionObject.setLocalTranslation(oldLoc);
        }
    }
}